#include "fuzzyxmlparser.h"
#include "trianglemf.h"
#include "trapezoidmf.h"
#include "messagedisplay.h"

FuzzyXmlParser::FuzzyXmlParser(const QString &fileName) :
        XmlParser(fileName)
{
}

void FuzzyXmlParser::loadRuleFile(QVector<Rule *> *ruleList) {

    /* Make sure that we aren't adding countless rule lists to each other */
    ruleList->clear();

    /* Load up the file */
    this->loadObject("Rule_list");

    /* Get the number of rules */
    int size = this->loadAttribute("Size").toInt();

    /* Get <Size> number of rules from the file */
    for(int i = 0; i < size; ++i ) {

        this->loadObject("Rule");
        ruleList->push_back(new Rule(this->loadAttribute("Input_1"),
                                     this->loadAttribute("Input_2"),
                                     this->loadAttribute("Output")));
        this->closeObject("Rule");
    }

    /* Close the file */
    this->closeObject("Rule_list");

}

void FuzzyXmlParser::loadCollectionFile(Collection* collection, bool isOutput)
{

    /* Make sure that the collection doesn't contain any old sets, so that we
     * aren't stacking collections on top of each other
     */
    collection->clear();

    /* Load up the file */
    this->loadObject("Collection");

    /* Get the number of sets in this collection */
    int size = this->loadAttribute("Size").toInt();
    collection->setSize(size);

    for(int i = 0; i < size; ++i ) {

        this->loadObject("Fuzzy_set");

        QString type = this->loadAttribute("Type");

        GraphicalMF* mfPtr = 0;

        /* Set the MF to be the kind that it asks for. */
        if(type.contains("Triangle")) mfPtr = this->loadTriangle();
        else if(type.contains("Trapezoid")) mfPtr = this->loadTrapezoid();
        else if(type.contains("Left End")) mfPtr = this->loadLeftEnd();
        else if(type.contains("Right End")) mfPtr = this->loadRightEnd();
        else {
            (new MessageDisplay("The type of a membership function was not "
                                 "recognised",
                                 "File Read Error"))->show();
            return;
        }

        if (isOutput) {
            mfPtr->setOutput(true);
            mfPtr->setFuzzyValue(0.0);
        }

        this->closeObject("Fuzzy_set");

        collection->setMF(i, mfPtr);
    }

    /* Set it to be an output collection if it is one */
    if ( isOutput ) collection->setOutput(true);

    this->closeObject("Collection");
}

TriangleMF* FuzzyXmlParser::loadTriangle() {

    QString name = this->loadAttribute("Name");

    QScopedArrayPointer<double> points(this->loadPoints(3));

    TriangleMF* mfPtr = new TriangleMF(points.data());
    mfPtr->setName(name);

    return mfPtr;
}

TrapezoidMF* FuzzyXmlParser::loadTrapezoid() {

    QString name = this->loadAttribute("Name");

    QScopedArrayPointer<double> points(this->loadPoints(4));

    TrapezoidMF* mfPtr = new TrapezoidMF(points.data());
    mfPtr->setName(name);

    return mfPtr;
}

LeftEndMF* FuzzyXmlParser::loadLeftEnd() {

    QString name = this->loadAttribute("Name");

    QScopedArrayPointer<double> points(this->loadPoints(3));

    LeftEndMF* mfPtr = new LeftEndMF(points.data());
    mfPtr->setName(name);

    return mfPtr;
}

RightEndMF* FuzzyXmlParser::loadRightEnd() {

    QString name = this->loadAttribute("Name");

    QScopedArrayPointer<double> points(this->loadPoints(3));

    RightEndMF* mfPtr = new RightEndMF(points.data());
    mfPtr->setName(name);

    return mfPtr;
}

double* FuzzyXmlParser::loadPoints(const int &nPoints) {

    this->loadObject("Point_list");

    double* points = new double[nPoints];

    for( int i = 0; i < nPoints; ++i )
        points[i] = this->loadAttribute("Point").toDouble();

    this->closeObject("Point_list");

    return points;
}
